home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / aminet / util / pack / ppcompress095.lha / ppcompress.c < prev    next >
C/C++ Source or Header  |  1992-11-14  |  8KB  |  354 lines

  1. #include <exec/types.h>
  2. #include <exec/memory.h>
  3. #include <dos/dos.h>
  4. #include <clib/exec_protos.h>
  5. #include <clib/dos_protos.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include <stdio.h>
  9. /* if you define NO_PRAGMAS before including proto/powerpacker.h */
  10. /* you must link with ppSCglue.o or ppLCglue.o                   */
  11. #include <proto/powerpacker.h>
  12. #include <libraries/ppbase.h>
  13. #include "ppcompress.h"
  14.  
  15.  
  16. struct PPBase    *PPBase    = NULL;    /* Home of PP */
  17. APTR        ci    = NULL;    /* PP's CrunchInfo array */
  18. char    *myname;        /* program name, for operation diagnostic */
  19. BPTR    fp;    /* global filehandle */
  20. char    *fn;            /* global filename ptr for user messages */
  21. UBYTE    *data    = NULL;        /* PP's data buffer */
  22. ULONG    datalen;        /* length of PP's data buffer */
  23. BOOL    enforce        = 1;    /* whether to enforce '.pp' extensions */
  24. char    ppsuff[]    = ".pp";    /* filename extension (not?) to enforce */
  25. char    userbreak[]    = "User break";    /* what to say when user kills me */
  26. struct FileInfoBlock    *fib;
  27. int    filesdone = 0;
  28.  
  29. /* prototypes */
  30. void    main(int, char **);
  31. void    process(char *, ULONG, ULONG, int);
  32. char    *tagname(char *, char *);
  33. char    *untagname(char *, char *);
  34. BOOL    uncrunch(char *, int);
  35. BOOL    crunch(char *, ULONG, ULONG, int);
  36. void    Usage(void);
  37. BOOL __stdargs __saveds    chkbrk(ULONG, ULONG, ULONG, APTR);
  38. void    clean(int, unsigned char);
  39.  
  40. extern char *GetMyStdIn(char *);
  41. extern BOOL PutMyStdOut(UBYTE *, int);
  42.  
  43. char version[]="$VER: PPCompress/PPUnCompress/PPCat 0.95 (14.11.92)";
  44.  
  45.  
  46. void main(int ac, char **av) {
  47. char    option;
  48. ULONG    eff=CRUN_VERYGOOD, speedup=SPEEDUP_BUFFMEDIUM;
  49. char    *optarg;
  50. int    i;
  51. char    tmpbuf[L_tmpnam+1];
  52.  
  53.     if ( ac == 0 ) clean(20, QUIT);
  54.  
  55.     fn=myname=av[0];
  56.     shift;
  57.  
  58.     if ( !(PPBase = (struct PPBase *)OpenLibrary ("powerpacker.library", 35L)) ) {
  59.         fail("You need powerpacker.library V35+");
  60.         clean(20, QUIT);
  61.     }
  62.  
  63.     while ( ac ) {
  64.         if (USER_HIT_CTRL_C) {
  65.             info(userbreak);
  66.             clean(10, QUIT);
  67.         }
  68.         if ( av[0][0] ==  '-' ) {
  69.             option    = av[0][1];
  70.             if ( strlen(av[0]) == 2 ) {
  71.                 shift;
  72.                 optarg=av[0];
  73.             }
  74.             else optarg=&av[0][2];
  75.             switch ( option ) {
  76.             case 'h':
  77.                 Usage();
  78.                 clean(NULL, QUIT);
  79.                 break;
  80.             case 'p':
  81.                 i = atoi(optarg);
  82.                 if ( (i != 0) && (i != 1) ) {
  83.                     fail("-p must signal 0 or 1");
  84.                     clean(10, QUIT);
  85.                 }
  86.                 else enforce = i;
  87.                 break;
  88.             case 'e':
  89.                 switch ( optarg[0] ) {
  90.                 case 'f':
  91.                     eff=CRUN_FAST;
  92.                     break;
  93.                 case 'm':
  94.                     eff=CRUN_MEDIOCRE;
  95.                     break;
  96.                 case 'g':
  97.                     eff=CRUN_GOOD;
  98.                     break;
  99.                 case 'v':
  100.                     eff=CRUN_VERYGOOD;
  101.                     break;
  102.                 case 'b':
  103.                     eff=CRUN_BEST;
  104.                     break;
  105.                 default:
  106.                     fail("Unknown efficiency");
  107.                     clean(10, QUIT);
  108.                     break;
  109.                 }
  110.                 break;
  111.             case 'b':
  112.                 switch ( optarg[0] ) {
  113.                 case 's':
  114.                     speedup=SPEEDUP_BUFFSMALL;
  115.                     break;
  116.                 case 'm':
  117.                     speedup=SPEEDUP_BUFFMEDIUM;
  118.                     break;
  119.                 case 'l':
  120.                     speedup=SPEEDUP_BUFFLARGE;
  121.                     break;
  122.                 default:
  123.                     fail("Unknown speedup");
  124.                     clean(10, QUIT);
  125.                     break;
  126.                 }
  127.                 break;
  128.             }
  129.             shift;
  130.         }
  131.         else {
  132.             process(av[0], eff, speedup, FILE);
  133.             shift;
  134.             filesdone++;
  135.         }
  136.     }
  137.     if ( !filesdone ) process(GetMyStdIn(tmpbuf), eff, speedup, PIPE);
  138.     DeleteFile(tmpbuf);
  139.     clean(0, QUIT);
  140. }
  141.  
  142. void process(char *file, ULONG eff, ULONG speedup, int mode) {
  143.  
  144.     fn = file;
  145.  
  146.     if ( !strcmp(myname, "ppcompress") ) crunch(file, eff, speedup, mode);
  147.     else if ( !strcmp(myname, "ppuncompress") ) uncrunch(file, mode);
  148.     else if ( !strcmp(myname, "ppcat") ) uncrunch(file, PIPE);
  149.     else {
  150.         fail("Must be ppcompress, ppuncompress, or ppcat");
  151.         clean(10, QUIT);
  152.     }
  153.  
  154.     return;
  155. }
  156.  
  157. char *tagname(char *in, char *out) {
  158.  
  159.     if ( !enforce ) strncpy(out, in, 30);    /* if no ext enforcing, don't tag */
  160.     else {
  161.         strncpy(out, in, 27);
  162.         strcat (out, ppsuff);
  163.     }
  164.     return (out);
  165. }
  166.  
  167. char *untagname(char *in, char *out) {
  168. char    *p;
  169. BPTR    tmpfp;
  170.  
  171.     strncpy(out, in, 30);
  172.     if ( p=strrchr(out, '.') ) {
  173.         if ( !strcmp(p, ppsuff) ) *p='\0';
  174.         if ( !(tmpfp = Open(in, MODE_OLDFILE)) ) {
  175.             p = &in[(strlen(in)>27?27:strlen(in))];
  176.             strcpy (p, ppsuff);
  177.         }
  178.         else Close(tmpfp);
  179.     }
  180.     return(in);
  181. }
  182.  
  183. BOOL uncrunch(char *in_fn, int mode) {
  184. int err;
  185. char in_fn2[31];
  186. char out_fn[31];
  187.  
  188.     strncpy(in_fn2, in_fn, 30);
  189.     in_fn = untagname(in_fn2, out_fn);
  190.     err = ppLoadData(in_fn, DECR_NONE, MEMF_PUBLIC, &data, &datalen, NULL);
  191.     if ( err ) {
  192.         fail(ppErrorMessage(err));
  193.         return(FALSE);
  194.     }
  195.     if ( mode == FILE ) {
  196.         fn=out_fn;
  197.         if ( !(fp=(BPTR)Open(out_fn, MODE_NEWFILE)) ) {
  198.             fail("Could not create file");
  199.             clean(20, FREEMEM);
  200.             return(FALSE);
  201.         }
  202.         if ( Write(fp, data, datalen) != datalen ) {
  203.             fail("Could not write whole file");
  204.             clean(20, CLOSEFP | FREEMEM);
  205.             return(FALSE);
  206.         }
  207.         clean(0, CLOSEFP | FREEMEM);
  208.         if ( strcmp(in_fn, out_fn) ) {
  209.             if ( !(DeleteFile(in_fn)) ) {
  210.                 fn=in_fn;
  211.                 fail("Could not delete file");
  212.             }
  213.         }
  214.     }
  215.     else {
  216.     BOOL stat;
  217.         stat=PutMyStdOut(data, datalen);
  218.         clean(0, FREEMEM);
  219.         if ( !stat ) {
  220.             Write(Output(), "\n", 1);
  221.             return(FALSE);
  222.         }
  223.     }
  224.  
  225.     return(TRUE);
  226. }
  227.  
  228. BOOL crunch(char *in_fn, ULONG eff, ULONG speedup, int mode) {
  229. ULONG    crunchlen;
  230. char    out_fn[31];
  231. BPTR    lock;
  232.  
  233.     if ( !(ci = ppAllocCrunchInfo(eff, speedup, chkbrk, NULL)) ) {
  234.         fail("Can't allocate crunch space");
  235.         clean(20, QUIT);
  236.     }
  237.  
  238.     if ( (fp=(BPTR)Open(in_fn, MODE_OLDFILE)) == NULL ) {
  239.         fail("Could not open file");
  240.         clean(0, FREECI);
  241.         return(FALSE);
  242.     }
  243.     if ( !(fib = AllocMem(sizeof(struct FileInfoBlock), MEMF_PUBLIC)) ) {
  244.         fail("Could not get data size");
  245.         clean(20, FREECI);
  246.     }
  247.     if ( !(lock = Lock(in_fn, ACCESS_READ)) ) {
  248.         fail("Could not lock file");
  249.         clean(0, CLOSEFP | FREECI | FREEFIB);
  250.         return(FALSE);
  251.     }
  252.     if ( !(Examine(lock, fib)) ) {
  253.         fail("Could not stat file");
  254.         UnLock(lock);
  255.         clean(0, CLOSEFP | FREECI | FREEFIB);
  256.         return(FALSE);
  257.     }
  258.     UnLock(lock);
  259.     if ( fib->fib_DirEntryType > 0 ) {
  260.         clean(0, CLOSEFP | FREECI | FREEFIB);
  261.         return(FALSE);        /* ignore any dirs in list */
  262.     }
  263.     datalen=fib->fib_Size;
  264.     FreeMem(fib, sizeof(struct FileInfoBlock));
  265.     if ( !(data=AllocMem(datalen, MEMF_PUBLIC)) ) {
  266.         fail("Could not allocate a crunch buffer");
  267.         clean(0, CLOSEFP | FREECI);
  268.         return(FALSE);
  269.     }
  270.     if ( Read(fp, data, datalen) != datalen ) {
  271.         fail("Could not read whole file");
  272.         clean(0, CLOSEFP | FREEMEM | FREECI);
  273.         return(FALSE);
  274.     }
  275.  
  276.     switch ( crunchlen=ppCrunchBuffer(ci, data, datalen) ) {
  277.     case    PP_CRUNCHABORTED:
  278.         info(userbreak);
  279.         clean(0, CLOSEFP | FREEMEM | FREECI);
  280.         return(FALSE);
  281.     case    PP_BUFFEROVERFLOW:
  282.         fail("Buffer overflow; no compression possible");
  283.         clean(0, CLOSEFP | FREEMEM | FREECI);
  284.         return(FALSE);
  285.     default:
  286.         clean(0, CLOSEFP | FREECI);
  287.     }
  288.  
  289.     if ( mode == FILE ) {
  290.         tagname(in_fn, out_fn);
  291.         fn=out_fn;
  292.         if ( !(fp=(BPTR)Open(out_fn, MODE_NEWFILE)) ) {
  293.             fail("Could not create file");
  294.             clean(20, FREEMEM);
  295.             return(FALSE);
  296.         }
  297.         if ( !(ppWriteDataHeader(fp, eff, FALSE, NULL)) ) {
  298.             fail("Could not write PP header");
  299.             clean(20, CLOSEFP | FREEMEM);
  300.             return(FALSE);
  301.         }
  302.         if ( Write(fp, data, crunchlen) != crunchlen ) {
  303.             fail("Could not write whole file");
  304.             clean(20, CLOSEFP | FREEMEM);
  305.             return(FALSE);
  306.         }
  307.         clean(0, CLOSEFP | FREEMEM);
  308.         if ( enforce ) {
  309.             if ( !(DeleteFile(in_fn)) ) {
  310.                 fn=in_fn;
  311.                 fail("Could not delete file");
  312.             }
  313.         }
  314.     }
  315.     else {
  316.     BOOL stat;
  317.         if ( !(ppWriteDataHeader(Output(), eff, NULL, NULL)) ) {
  318.             fail("Could not write PP header");
  319.             clean(20, FREEMEM);
  320.             return(FALSE);
  321.         }
  322.         stat=PutMyStdOut(data, crunchlen);
  323.         clean(0, FREEMEM);
  324.         if ( !stat ) return(FALSE);
  325.     }
  326.  
  327.     return(TRUE);
  328. }
  329.  
  330. void Usage(void) {
  331.     fprintf(stderr, "%s: Usage:\n%s [-p 0|1] [-e f|m|g|v|b] [-b s|m|l] file [file [...] ]\n",myname, myname);
  332.     return;
  333. }
  334.  
  335. /* callback func for ppcruncher; check for user break */
  336. BOOL __stdargs __saveds chkbrk(ULONG lensofar, ULONG crunlen, ULONG totlen, APTR userdata) {
  337.     if (USER_HIT_CTRL_C) return(FALSE);
  338.     else return(TRUE);
  339. }
  340.  
  341. /* use this to free global allocations or to quit */
  342. void clean(int code, unsigned char flags) {
  343.     /* free all resources */
  344.     if (flags & FREEFIB)    FreeMem(fib, sizeof(struct FileInfoBlock));
  345.     if (flags & FREECI)    ppFreeCrunchInfo(ci);
  346.     if (flags & FREEMEM)    FreeMem (data, datalen);
  347.     if (flags & CLOSEFP)    Close(fp);
  348.     if (flags & QUIT) {
  349.         if (PPBase)    CloseLibrary ((struct Library *)PPBase);
  350.         exit (code);
  351.     }
  352.     else return;
  353. }
  354.